<?php

namespace app\meizhuangapi\service\order;

use app\api\service\order\Checkout as CheckoutCon;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\meizhuangapi\model\UserCoupon as UserCouponModel;
use app\meizhuangapi\model\Order as OrderModel;
use app\common\model\Wxapp as WxappModel;
use app\meizhuangapi\model\dealer\Referee as RefereeModel;
use app\meizhuangapi\model\User as UserModel;
use app\meizhuangapi\model\dealer\Order as DealerOrderModel;
use app\meizhuangapi\service\Payment as PaymentService;
use app\common\service\goods\source\Factory as StockFactory;
use think\Db;
use app\api\service\User as UserService;
/**
 * 订单结算台服务类
 * Class Checkout
 * @package app\api\service\order
 */
class Checkout extends CheckoutCon
{
    /**
     * 创建新订单
     */
    public function createOrder($order)
    {
        // 表单验证
        if (!$this->validateOrderForm($order, $this->param['linkman'], $this->param['phone'],$this->param['coupon_id'])) {
            return false;
        }
        // 创建新的订单
//        $status = $this->model->transaction(function () use ($order) {
//            // 创建订单事件
//            return $this->createOrderEvent($order);
//        });
       
        $status = $this->createOrderEvent($order);

        // 余额支付标记订单已支付
        if ($status && $order['pay_type'] == PayTypeEnum::BALANCE) {

            if($order['is_use_balance']==1){
                $this->error = '余额支付不支持零钱抵扣';
                return false;
            }
            if($order['coupon_id']!=0){
                $this->error = '余额支付不支持优惠券抵扣';
                return false;
            }
            if($order['is_use_balance']==1 && $order['coupon_id']!=0){
                $this->error = '优惠券和零钱不能同时抵扣';
                return false;
            }
            //return $this->model->onPaymentByBalance($this->model['order_no']);
            return $this->model->onPaymentByBalances($this->user,$this->model);
        }
        return $status;
    }

    /**
     * 创建订单事件
     * @param $order
     * @return bool
     * @throws BaseException
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    private function createOrderEvent($order)
    {
        $this->log->info('开始','新建订单事务');
        // 新增订单记录
        $status = $this->add($order, $this->param['remark']);
        $this->log->info(bool2str($status),'订单表新增记录');
        if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
            // 记录收货地址
            $ret = $this->saveOrderAddress($order['address'],$order['wxapp_id']);
            $this->log->info(bool2str($ret),'记录收货地址');
        } elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
            // 记录自提信息

            $ret = $this->saveOrderExtract($this->param['linkman'], $this->param['phone'],$order['wxapp_id']);
            $this->log->info(bool2str($ret),'记录自提信息');
        }
        // 保存订单商品信息
        $ret = $this->saveOrderGoods($order);
        $this->log->info(bool2str($ret),'保存订单商品信息');
        // 更新商品库存 (针对下单减库存的商品)
        $ret = $this->updateGoodsStockNum($order);
        $this->log->info(bool2str($ret),'更新商品库存 ');
        // 设置优惠券使用状态
        $ret = UserCouponModel::setIsUse($this->param['coupon_id']);
        $this->log->info(bool2str($ret),'设置优惠券使用状态 ');
        // 积分抵扣情况下扣除用户积分
        if ($order['is_allow_points'] && $order['is_use_points'] && $order['points_num'] > 0) {
            $describe = "用户消费：{$this->model['order_no']}";
            $ret = $this->user->setIncPoints(-$order['points_num'], $describe);
            $this->log->info(bool2str($ret),'积分抵扣情况下扣除用户积分 ');
        }

        // 零钱抵扣情况下扣除用户零钱
        if ($order['is_allow_balance'] && $order['is_use_balance'] && $order['balance_num'] > 0) {
            $describe = "{$this->model['order_no']}";
            $ret = $this->user->setIncBalance(-$order['balance_num'], $describe,20);
            $this->log->info(bool2str($ret),'零钱抵扣情况下扣除用户零钱 ');
        }

        // 获取订单详情
        $detail = OrderModel::getUserOrderDetail($this->model['order_id'], $this->user['user_id']);
        if($detail['pay_type']['value']==20){
            //查看商户设置的分销方案
            $dealer_case = WxappModel::dealerCase($detail['wxapp_id']);

            //查看上级用户是否满足分销条件
            if ($refereeId = RefereeModel::isExistReferee($this->user['user_id'])) {
                $this->log->info('true','查看上级用户是否满足分销条件');
                //查看上级是否满足分销条件
                $refereeModel = new UserModel;
                $refereeInfo = $refereeModel::detail($refereeId);
                //如果为分销方案一
                if($dealer_case==1){
                    $checkDealer = $refereeModel->getConfigByUserType($refereeInfo,$type="goods");
                    if($checkDealer){
                    $this->log->info('开始','创建方案一分销商订单');
                        // 方案一记录分销商订单
                        DealerOrderModel::createOrder($detail,$refereeId);
                    }
                }elseif($dealer_case==2){//分销方案二
                    $checkDealerTow = $refereeInfo->getDealerTow($refereeInfo,$type="product_status");
                    if($checkDealerTow){
                    $this->log->info('开始','创建方案二分销商订单');
                        // 方案二记录分销商订单
                        DealerOrderModel::createOrderTow($detail,$refereeId,$checkDealerTow);
                    }
                }
            }
        }
        $this->log->info('结束','新建订单事务');
        return $status;
    }

    /**
     * 构建支付请求的参数
     * @return array
     * @throws BaseException
     * @throws \think\exception\DbException
     */
    public function onOrderPayment()
    {
        return PaymentService::orderPayment($this->user, $this->model, $this->param['pay_type']);
    }

    /**
     * 表单验证 (订单提交)
     * @param array $order 订单信息
     * @param string $linkman 联系人
     * @param string $phone 联系电话
     * @return bool
     */
    private function validateOrderForm(&$order, $linkman, $phone,$coupon_id)
    {

        // 判断零钱支付和优惠券
        if ($order['is_allow_balance']  && $order['balance_num'] > 0 &&  $order['is_use_balance'] > 0) {
            if ($this->user['balance'] < $order['balance_num']) {
                $this->error = '您的零钱不足，无法使用零钱抵扣';
                return false;
            }
        }

        // 判断零钱支付和优惠券
        if ($order['is_allow_balance']  && $order['is_use_balance'] > 0 && $coupon_id) {
            $this->error = '优惠券和零钱不能同时抵扣';
            return false;
        }

        if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
            if (empty($order['address'])) {
                $this->error = '您还没有选择配送地址';
                return false;
            }
        }

        if ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
            if (empty($order['extract_shop'])) {
                $this->error = '您还没有选择自提门店';
                return false;
            }
            if (empty($linkman) || empty($phone)) {
                $this->error = '您还没有填写联系人和电话';
                return false;
            }
        }
        // 余额支付时判断用户余额是否足够
        if ($order['pay_type'] == PayTypeEnum::BALANCE) {
            //获取用户收益总金额
            $money=Db::name('dealer_user')->where(['user_id'=>$this->user['user_id']])->find();
            if (($this->user['money'] < $order['order_pay_price'])&&($money['money']<$order['order_pay_price'])) {
                $this->error = '您的余额不足，无法使用余额支付';
                return false;
            }
        }

        return true;
    }

    /**
     * 当前订单是否存在和使用积分抵扣
     * @param $order
     * @return bool
     */
    private function isExistPointsDeduction($order)
    {
        return $order['is_allow_points'] && $order['is_use_points'];
    }

    /**
     * 当前订单是否存在和使用零钱抵扣
     * @param $order
     * @return bool
     */
    private function isExistBalanceDeduction($order)
    {
        return $order['is_allow_balance'] && $order['is_use_balance'];
    }

    /**
     * 新增订单记录
     * @param $order
     * @param string $remark
     * @return false|int
     */
    private function add($order, $remark = '')
    {
        foreach($order['goods_list'] as $k=>&$v){
            $goodsinfo = $v->toarray();
            $array_is_fictitious[] = $goodsinfo['is_fictitious'];
        }
        if(in_array(2,$array_is_fictitious)){
            $is_fictitious = 2;
        }else{
            $is_fictitious = 1;
        }

        // 当前订单是否存在和使用积分抵扣
        $isExistPointsDeduction = $this->isExistPointsDeduction($order);
        // 当前订单是否存在使用零钱抵扣
        $isExistBalanceDeduction = $this->isExistBalanceDeduction($order);
        // 订单数据
        $data = [
            'user_id' => $this->user['user_id'],
            'order_no' => $this->model->orderNo(),
            'total_price' => $order['order_total_price'],
            'order_price' => $order['order_price'],
            'coupon_id' => $order['coupon_id'],
            'coupon_money' => $order['coupon_money'],
            'points_money' => $isExistPointsDeduction ? $order['points_money'] : 0.00,
            'points_num' => $isExistPointsDeduction ? $order['points_num'] : 0,
            'balance_money' => $isExistBalanceDeduction ? $order['balance_money'] : 0.00,
            'balance_num' => $isExistBalanceDeduction ? $order['balance_num'] : 0,
            'pay_price' => $order['order_pay_price'],
            'delivery_type' => $order['delivery'],
            'pay_type' => $order['pay_type'],
            'pay_status' => 10,
            'buyer_remark' => trim($remark),
            'order_source' => $this->orderSource['source'],
            'order_source_id' => $this->orderSource['source_id'],
            'points_bonus' => $order['points_bonus'],
            'is_fictitious' => $is_fictitious,
            'wxapp_id' => $order['wxapp_id'],
        ];
        if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
            $data['express_price'] = $order['express_price'];
        } elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
            $data['extract_shop_id'] = $order['extract_shop']['shop_id'];
        }
        // 保存订单记录
        return $this->model->save($data);
    }

    /**
     * 保存订单商品信息
     * @param $order
     * @return int
     */
    private function saveOrderGoods($order)
    {
        // 当前订单是否存在和使用积分抵扣
        $isExistPointsDeduction = $this->isExistPointsDeduction($order);
        // 当前订单是否存在使用零钱抵扣
        $isExistBalanceDeduction = $this->isExistBalanceDeduction($order);

        // 订单商品列表
        $goodsList = [];
        foreach ($order['goods_list'] as $goods) {
            /* @var GoodsModel $goods */
            $item = [
                'user_id' => $this->user['user_id'],
                'wxapp_id' => $order['wxapp_id'],
                'goods_id' => $goods['goods_id'],
                'goods_name' => $goods['goods_name'],
                'image_id' => $goods['image'][0]['image_id'],
                'deduct_stock_type' => $goods['deduct_stock_type'],
                'spec_type' => $goods['spec_type'],
                'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
                'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
                'goods_attr' => $goods['goods_sku']['goods_attr'],
                'content' => $goods['content'],
                'goods_no' => $goods['goods_sku']['goods_no'],
                'goods_price' => $goods['goods_sku']['goods_price'],
                'line_price' => $goods['goods_sku']['line_price'],
                'goods_weight' => $goods['goods_sku']['goods_weight'],
                'is_user_grade' => (int)$goods['is_user_grade'],
                'grade_ratio' => $goods['grade_ratio'],
                'grade_goods_price' => $goods['grade_goods_price'],
                'grade_total_money' => $goods['grade_total_money'],
                'coupon_money' => $goods['coupon_money'],
                'points_money' => $isExistPointsDeduction ? $goods['points_money'] : 0.00,
                'points_num' => $isExistPointsDeduction ? $goods['points_num'] : 0,
                'balance_money' => $isExistBalanceDeduction ? $goods['balance_money'] : 0.00,
                'balance_num' => $isExistBalanceDeduction ? $goods['balance_num'] : 0,
                'points_bonus' => $goods['points_bonus'],
                'total_num' => $goods['total_num'],
                'total_price' => $goods['total_price'],
                'total_pay_price' => $goods['total_pay_price'],
                'is_ind_dealer' => $goods['is_ind_dealer'],
                'dealer_money_type' => $goods['dealer_money_type'],
                'first_money' => $goods['first_money'],
                'second_money' => $goods['second_money'],
                'third_money' => $goods['third_money'],
                'is_fictitious' => $goods['is_fictitious'],
            ];
            // 记录订单商品来源id
            $item['goods_source_id'] = isset($goods['goods_source_id']) ? $goods['goods_source_id'] : 0;
            $goodsList[] = $item;
        }
        return $this->model->goods()->saveAll($goodsList);
    }

    /**
     * 更新商品库存 (针对下单减库存的商品)
     * @param $order
     * @return mixed
     */
    private function updateGoodsStockNum($order)
    {

        return StockFactory::getFactory($this->model['order_source'])->updateGoodsStock($order['goods_list']);
    }

    /**
     * 记录收货地址
     * @param $address
     * @return false|\think\Model
     */
    private function saveOrderAddress($address,$wxapp_id=null)
    {
        if ($address['region_id'] == 0 && !empty($address['district'])) {
            $address['detail'] = $address['district'] . ' ' . $address['detail'];
        }
        return $this->model->address()->save([
            'user_id' => $this->user['user_id'],
            'wxapp_id' => $wxapp_id,
            'name' => $address['name'],
            'phone' => $address['phone'],
            'province_id' => $address['province_id'],
            'city_id' => $address['city_id'],
            'region_id' => $address['region_id'],
            'detail' => $address['detail'],
        ]);
    }

    /**
     * 保存上门自提联系人
     * @param $linkman
     * @param $phone
     * @return false|\think\Model
     */
    private function saveOrderExtract($linkman, $phone,$wxapp_id=null)
    {
        // 记忆上门自提联系人(缓存)，用于下次自动填写
        UserService::setLastExtract($this->model['user_id'], trim($linkman), trim($phone));
        // 保存上门自提联系人(数据库)
        return $this->model->extract()->save([
            'linkman' => trim($linkman),
            'phone' => trim($phone),
            'user_id' => $this->model['user_id'],
            'wxapp_id' => $wxapp_id,
        ]);
    }

    /**
     * 设置错误信息
     * @param $error
     */
    protected function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    /**
     * 获取错误信息
     * @return mixed
     */
    public function getError()
    {
        return $this->error ?: '';
    }

    /**
     * 是否存在错误
     * @return bool
     */
    public function hasError()
    {
        return !empty($this->error);
    }

}